home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / src / panelize.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  10.2 KB  |  424 lines

  1. /* External panelize
  2.    Copyright (C) 1995 The Free Software Foundation
  3.    
  4.    Written by: 1995 Janne Kukonlehto
  5.                1995 Jakub Jelinek
  6.  
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.  
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
  20.  */
  21.  
  22. #include <config.h>
  23. #ifdef HAVE_UNISTD_H
  24. #   include <unistd.h>
  25. #endif
  26. #include <string.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>        /* For malloc() */
  29. #include <errno.h>
  30. #include <sys/types.h>
  31. #include <sys/param.h>
  32. #include <sys/stat.h>
  33. #include <grp.h>
  34. #include <pwd.h>
  35. #include "tty.h"
  36. #include "mad.h"
  37. #include "util.h"        /* Needed for the externs */
  38. #include "win.h"
  39. #include "color.h"
  40. #include "dlg.h"
  41. #include "widget.h"
  42. #include "dialog.h"        /* For do_refresh() */
  43. #include "setup.h"        /* For profile_bname */
  44. #include "profile.h"        /* Load/save directories panelize */
  45. #include "fs.h"
  46.  
  47. /* Needed for the extern declarations of integer parameters */
  48. #define DIR_H_INCLUDE_HANDLE_DIRENT
  49. #include "dir.h"
  50. #include "panel.h"        /* Needed for the externs */
  51. #include "file.h"
  52. #include "main.h"
  53. #include "global.h"
  54.  
  55. void do_external_panelize (char *command);
  56.  
  57. #define UX        5
  58. #define UY        2
  59.  
  60. #define BX        5
  61. #define BY        18
  62.  
  63. #define BUTTONS        4
  64. #define LABELS          3
  65. #define B_ADD        B_USER
  66. #define B_REMOVE        B_USER + 1
  67.  
  68. static WListbox *l_panelize;
  69.  
  70. static Dlg_head *panelize_dlg;
  71.  
  72. static WInput *pname;
  73.  
  74. static char *panelize_section = "Panelize";
  75.  
  76. static int last_listitem;
  77.  
  78. struct {
  79.     int ret_cmd, y, x;
  80.     char *text;
  81.     int hkey, hpos;
  82. } panelize_but[BUTTONS] = {
  83.     { B_CANCEL, 0, 53, "[ Cancel ]",  'c', 2, },
  84.     { B_ADD,    0, 28, "[ Add new ]", 'a', 2, },
  85.     { B_REMOVE, 0, 16, "[ Remove ]",  'r', 2, },
  86.     { B_ENTER,  0,  0, "[[ Panelize ]]", 'p', 5, },
  87. };
  88.  
  89. /* Directory panelize */
  90. static struct panelize{
  91.     char *command;
  92.     char *label;
  93.     struct panelize *next;
  94. } *panelize = NULL;
  95.  
  96. #ifndef HAVE_X
  97. static void panelize_refresh (void)
  98. {
  99.     attrset (REVERSE_COLOR);
  100.     dlg_erase (panelize_dlg);
  101.     
  102.     draw_box (panelize_dlg, 1, 2, 20, 70);
  103.     draw_box (panelize_dlg, UY, UX, 12, 63);
  104.     
  105.     attrset (COLOR_HOT_NORMAL);
  106.     dlg_move (panelize_dlg, 1, (72 - 19) / 2);
  107.     addstr (" External panelize ");
  108. }
  109. #endif
  110.  
  111. static INLINE void update_command ()
  112. {
  113.     if (l_panelize->pos != last_listitem) {
  114.         last_listitem = l_panelize->pos;
  115.         assign_text (pname, 
  116.             ((struct panelize *) l_panelize->current->data)->command);
  117.     pname->point = 0;
  118.         update_input (pname);
  119.     }
  120. }
  121.  
  122. static int panelize_callback (Dlg_head * h, int Par, int Msg)
  123. {
  124.     switch (Msg) {
  125. #ifndef HAVE_X    
  126.     case DLG_DRAW:
  127.     panelize_refresh ();
  128.     break;
  129. #endif    
  130.  
  131.     case DLG_POST_KEY:
  132.     /* fall */
  133.     case DLG_INIT:
  134.     attrset (MENU_ENTRY_COLOR);
  135.     update_command ();
  136.     break;
  137.     }
  138.     return 0;
  139. }
  140.  
  141. static int l_call (void *data)
  142. {
  143.     return 1;
  144. }
  145.  
  146. static void init_panelize (void)
  147. {
  148.     int i;
  149.     struct panelize *current = panelize;
  150.     
  151.     last_listitem = 0;
  152.     
  153.     do_refresh ();
  154.  
  155.     panelize_dlg = create_dlg (0, 0, 22, 74, dialog_colors,
  156.                   panelize_callback, "[External panelize]", "Panelize",
  157.                   DLG_CENTER);
  158.     x_set_dialog_title (panelize_dlg, "External panelize");
  159.  
  160. #define XTRACT(i) BY+panelize_but[i].y, BX+panelize_but[i].x, panelize_but[i].ret_cmd, panelize_but[i].text, panelize_but[i].hkey, panelize_but[i].hpos, 0, 0
  161.  
  162.     for (i = 0; i < BUTTONS; i++)
  163.     add_widgetl (panelize_dlg, button_new (XTRACT (i)), (i == BUTTONS - 1) ?
  164.         XV_WLAY_CENTERROW : XV_WLAY_RIGHTOF);
  165.  
  166.     pname = input_new (UY+14, UX, INPUT_COLOR, 63, "");
  167.     add_widgetl (panelize_dlg, pname, XV_WLAY_RIGHTOF);
  168.  
  169.     add_widgetl (panelize_dlg, label_new (UY+13, UX, "Command"), XV_WLAY_NEXTROW);
  170.  
  171.     /* get new listbox */
  172.     l_panelize = listbox_new (UY + 1, UX + 1, 61, 10, 0, l_call);
  173.  
  174.     while (current){
  175.     listbox_add_item (l_panelize, 0, 0, current->label, current);
  176.     current = current->next;
  177.     }
  178.  
  179.     /* add listbox to the dialogs */
  180.     add_widgetl (panelize_dlg, l_panelize, XV_WLAY_EXTENDWIDTH); 
  181.  
  182.     listbox_select_entry (l_panelize, 
  183.         listbox_search_text (l_panelize, "Other command"));
  184. }
  185.  
  186. static void panelize_done (void)
  187. {
  188.     destroy_dlg (panelize_dlg);
  189.     repaint_screen ();
  190. }
  191.  
  192. static void add2panelize (char *label, char *command)
  193. {
  194.     struct panelize *current, *old;
  195.  
  196.     old = NULL;
  197.     current = panelize;
  198.     while (current && strcmp (current->label, label) <= 0){
  199.     old = current;
  200.     current = current->next;
  201.     }
  202.  
  203.     if (old == NULL){
  204.     panelize = malloc (sizeof (struct panelize));
  205.     panelize->label = label;
  206.     panelize->command = command;
  207.     panelize->next = current;
  208.     } else {
  209.     struct panelize *new;
  210.     new = malloc (sizeof (struct panelize));
  211.     new->label = label;
  212.     new->command = command;
  213.     old->next = new;
  214.     new->next = current;
  215.     }
  216. }
  217.  
  218. void add2panelize_cmd (void)
  219. {
  220.     char *label;
  221.  
  222.     if (pname->buffer && (*pname->buffer)) {
  223.     label = input_dialog (" Add to external panelize ", "Unnamed find", 
  224.                   "");
  225.     if (!label)
  226.         return;
  227.     if (!*label) {
  228.         free (label);
  229.         return;
  230.     }
  231.     
  232.     add2panelize (label, strdup(pname->buffer));
  233.     }
  234. }
  235.  
  236. static void remove_from_panelize (struct panelize *entry)
  237. {
  238.     if (entry == panelize){
  239.     panelize = panelize->next;
  240.     } else {
  241.     struct panelize *current = panelize;
  242.     while (current && current->next != entry)
  243.         current = current->next;
  244.     if (current){
  245.         current->next = entry->next;
  246.     }
  247.     }
  248.     
  249.     /* FIXME: Commented out because freeing seems to cause corruption
  250.        after some add and remove operations */
  251.     /*free (entry->label);
  252.     free (entry->command);
  253.     free (entry);*/
  254. }
  255.  
  256. void external_panelize (void)
  257. {
  258.     char *target = NULL;
  259.  
  260.     init_panelize ();
  261.  
  262.     /* display file info */
  263.     attrset (SELECTED_COLOR);
  264.  
  265.     run_dlg (panelize_dlg);
  266.  
  267.     switch (panelize_dlg->ret_value) {
  268.     case B_CANCEL:
  269.     break;
  270.  
  271.     case B_ADD:
  272.     add2panelize_cmd ();
  273.     break;
  274.  
  275.     case B_REMOVE:
  276.     remove_from_panelize (l_panelize->current->data);
  277.     break;
  278.  
  279.     case B_ENTER:
  280.     target = pname->buffer;
  281.     if (target != NULL && *target) {
  282.         char *cmd = strdup (target);
  283.         destroy_dlg (panelize_dlg);
  284.         do_external_panelize (cmd);
  285.         free (cmd);
  286.         repaint_screen ();
  287.         return;
  288.     }
  289.     break;
  290.     }
  291.  
  292.     panelize_done ();
  293. }
  294.  
  295. void load_panelize (void)
  296. {
  297.     void *profile_keys;
  298.     char *key, *value;
  299.     
  300.     profile_keys = profile_init_iterator (panelize_section, profile_name);
  301.     
  302.     add2panelize (strdup ("Other command"), strdup (""));
  303.  
  304.     if (!profile_keys){
  305.     add2panelize (strdup ("Find rejects after patching"), strdup ("find . -name \\*.rej -print"));
  306.     add2panelize (strdup ("Find *.orig after patching"), strdup ("find . -name \\*.orig -print"));
  307.     add2panelize (strdup ("Find SUID and SGID programs"), strdup ("find . \\( \\( -perm -04000 -a -perm +011 \\) -o \\( -perm -02000 -a -perm +01 \\) \\) -print"));
  308.     return;
  309.     }
  310.     
  311.     while (profile_keys){
  312.     profile_keys = profile_iterator_next (profile_keys, &key, &value);
  313.     add2panelize (strdup (key), strdup (value));
  314.     }
  315. }
  316.  
  317. void save_panelize (void)
  318. {
  319.     struct panelize *current = panelize;
  320.     
  321.     profile_clean_section (panelize_section, profile_name);
  322.     for (;current; current = current->next){
  323.         if (strcmp (current->label, "Other command"))
  324.         WritePrivateProfileString (panelize_section,
  325.                        current->label,
  326.                        current->command,
  327.                        profile_name);
  328.     }
  329.     sync_profiles ();
  330. }
  331.  
  332. void done_panelize (void)
  333. {
  334.     struct panelize *current = panelize;
  335.     struct panelize *next;
  336.  
  337.     for (; current; current = next){
  338.     next = current->next;
  339.     free (current->label);
  340.     free (current->command);
  341.     free (current);
  342.     }
  343. }
  344.  
  345. struct spaced_dirent {
  346.     struct dirent dp;
  347. #ifdef NEED_EXTRA_DIRENT_BUFFER
  348.     char extra_buffer [MC_MAXPATHLEN];
  349. #endif
  350. };
  351.  
  352. void do_external_panelize (char *command)
  353. {
  354.     struct spaced_dirent dp;
  355.     int status, link_to_dir, stalled_link;
  356.     int next_free = 0;
  357.     struct stat buf;
  358.     dir_list *list = &cpanel->dir;
  359.     char line [MC_MAXPATHLEN];
  360.     FILE *external;
  361.  
  362.     open_error_pipe ();
  363.     external = popen (command, "r");
  364.     if (!external){
  365.     close_error_pipe (1, "Cannot invoke command.");
  366.     return;
  367.     }
  368.     clean_dir (list, cpanel->count);
  369.  
  370.     /* Clear the counters */
  371.     cpanel->total = cpanel->dirs_marked = cpanel->marked = 0;
  372.     while (1) {
  373.     clearerr(external);
  374.     if (fgets (line, MC_MAXPATHLEN, external) == NULL)
  375.         if (ferror(external) && errno == EINTR)
  376.         continue;
  377.         else
  378.         break;
  379.     if (line[strlen(line)-1] == '\n')
  380.         line[strlen(line)-1] = 0;
  381.     if (strlen(line) < 1)
  382.         continue;
  383.     if (line [0] == '.' && line[1] == PATH_SEP)
  384.         strcpy (dp.dp.d_name, line + 2);
  385.     else
  386.         strcpy (dp.dp.d_name, line);
  387. #if !defined(HAVE_DIRENT_H) && !defined(_POSIX_VERSION)
  388.     NLENGTH (&dp.dp) = strlen (dp.dp.d_name);
  389. #endif
  390.     status = handle_dirent (list, NULL, &dp.dp, &buf, next_free, &link_to_dir,
  391.         &stalled_link);
  392.     if (status == 0)
  393.         continue;
  394.     if (status == -1)
  395.         break;
  396.     list->list [next_free].fnamelen = NLENGTH (&(dp.dp));
  397.     list->list [next_free].fname = strdup (dp.dp.d_name);
  398.     list->list [next_free].cache = NULL;
  399.     file_mark (cpanel, next_free, 0);
  400.     list->list [next_free].f.link_to_dir = link_to_dir;
  401.     list->list [next_free].f.stalled_link = stalled_link;
  402.     list->list [next_free].buf = buf;
  403.     next_free++;
  404.     if (!(next_free & 32))
  405.         rotate_dash ();
  406.     }
  407.     if (next_free){
  408.     cpanel->count = next_free;
  409.     cpanel->is_panelized = 1;
  410.     if (list->list [0].fname [0] == PATH_SEP){
  411.         strcpy (cpanel->cwd, PATH_SEP_STR);
  412.         chdir (PATH_SEP_STR);
  413.     }
  414.     } else {
  415.     do_load_dir (list, cpanel->sort_type, cpanel->reverse, cpanel->case_sensitive, cpanel->filter);
  416.     cpanel->count = set_zero_dir (list);
  417.     }
  418.     if (pclose (external) < 0)
  419.     message (2, "External panelize", "Pipe close failed");
  420.     close_error_pipe (0, 0);
  421.     try_to_select (cpanel, NULL);
  422.     paint_panel (cpanel);
  423. }
  424.